
<template></template>

<script setup>
import * as THREE from 'three'
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { OimoPhysics } from 'three/addons/physics/OimoPhysics.js';

const geometry = new THREE.SphereGeometry(50);
const material = new THREE.MeshBasicMaterial({
  color: 0x0000ff, //设置材质颜色
  transparent: true,//开启透明
  opacity: 0.5,//设置透明度
});

const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(0, 200, 0)
const scene = new THREE.Scene()
scene.add(mesh)

// 给需要设置关键帧动画的模型命名
// mesh.name = "Box";
// const times = [0, 3, 6]; //时间轴上，设置三个时刻0、3、6秒
// // times中三个不同时间点，物体分别对应values中的三个xyz坐标
// const values = [0, 0, 0, 100, 0, 0, 0, 0, 100];
// // 0~3秒，物体从(0,0,0)逐渐移动到(100,0,0),3~6秒逐渐从(100,0,0)移动到(0,0,100)
// const posKF = new THREE.KeyframeTrack('Box.position', times, values);
// // 从2秒到5秒，物体从红色逐渐变化为蓝色
// const colorKF = new THREE.KeyframeTrack('Box.material.color', [2, 5], [1, 0, 0, 0, 0, 1]);
// // 1.3 基于关键帧数据，创建一个clip关键帧动画对象，命名"test"，持续时间6秒。
// const clip = new THREE.AnimationClip("test", 6, [posKF, colorKF]);

// // AnimationMixer播放关键帧动画AnimationClip

// // 前面代码, 已经编辑好一个模型mesh的关键帧动画AnimationClip, 如果你想播放动画，就要借助播放器AnimationMixer。
// //包含关键帧动画的模型对象作为AnimationMixer的参数创建一个播放器mixer
// const mixer = new THREE.AnimationMixer(mesh);

// // 执行播放器AnimationMixer的.clipAction()方法返回一个AnimationAction对象, AnimationAction对象用来控制如何播放，比如.play()方法。

// //AnimationMixer的`.clipAction()`返回一个AnimationAction对象
// const clipAction = mixer.clipAction(clip);
// //.play()控制动画播放，默认循环播放
// clipAction.play();


//点光源：两个参数分别表示光源颜色和光照强度
// 参数1：0xffffff是纯白光,表示光源颜色
// 参数2：1.0,表示光照强度，可以根据需要调整
// const pointLight = new THREE.PointLight(0xffffff, 1.0);
// pointLight.decay = 0.0;//设置光源不随距离衰减
// //点光源位置
// pointLight.position.set(200, 200, 300);//点光源放在x轴上
// scene.add(pointLight); //点光源添加到场景中

// // 点光源辅助可视化观察
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
// scene.add(pointLightHelper);
//环境光
const hesLight = new THREE.HemisphereLight() //白色光
hesLight.intensity = 0.3
scene.add(hesLight)
//平行光
const dirLight = new THREE.DirectionalLight() //太阳光
dirLight.position.set(5, 5, -5)
scene.add(dirLight)


// AxesHelper：辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

scene.background = new THREE.Color(0x888888)

const width1 = 800; //宽度
const height1 = 500; //高度
const camera = new THREE.PerspectiveCamera(30, width1 / height1, 1, 10000);
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(500, 500, 500);
// camera.lookAt(mesh.position);//指向mesh对应的位置
// // 改变相机观察目标点
camera.lookAt(250, 0, 250);

const renderer = new THREE.WebGLRenderer({
  antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio);

renderer.setClearColor(0x444444, 1); //设置背景颜色

renderer.setSize(window.innerWidth, window.innerHeight); //设置three.js渲染区域的尺寸(像素px)
renderer.render(scene, camera); //执行渲染操作
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);

// // 改变相机观察目标点 camera.lookAt(250, 0, 250);
// 意相机控件OrbitControls会影响lookAt设置，注意手动设置OrbitControls的目标参数
controls.target.set(250, 0, 250)
controls.update()

renderer.shadowMap.enabled = true
dirLight.castShadow = true

const clock = new THREE.Clock();
function render() {
  // const spt = clock.getDelta() * 1000;//毫秒
  // console.log('两帧渲染时间间隔(毫秒)', spt);
  // console.log('帧率FPS', 1000 / spt);
  renderer.render(scene, camera); //执行渲染操作
  // const frameT = clock.getDelta();
  // // 更新播放器相关的时间
  // mixer.update(frameT);
  // if (obj2.bool) mesh.rotateY(0.01); // GUI进行单选框控制是否旋转
  // mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
  requestAnimationFrame(render);//请求再次执行渲染函数render，渲染下一帧
}
render();


let ball
// 初始化物体
function initMeshes() {
  ball = new THREE.Mesh(
    new THREE.SphereGeometry(0.05, 32, 16),
    new THREE.MeshLambertMaterial()
  )
  ball.position.set(0, 2, 0)
  scene.add(ball)
}
// 初始化物体
initMeshes()


// 使用OimoPhysics物理引擎插件

// OimoPhysics 提供的是一个异步函数，我们可以直接调用它
//  OimoPhysics 提供了一个addMesh方法，通过该方法，可以将物体添加到OimoPhysics 创建的物理世界中，addMesh有两个参数，第一个参数是我们创建的物体模型，第二个参数代表该物体是否参与物理世界的运动，默认为0，即不参与，设置为1表示参与

// 前面我们已经引入了 OimoPhysics 插件，这里我们来使用它实现小球下落的过程
// 由于其是异步函数，我们通过await在等待其执行结果
//  首先我们新建一个变量来接收OimoPhysics 执行的结果

let physics

// 创建一个 enablePhysics() 函数，并调用OimoPhysics
// 刷新浏览器，我们看到小球有了下落的效果，但是，我们发现小球会一直下落，这不是我们想要的，需要添加地板floow
// async function enablePhysics() {
//   physics = await OimoPhysics()
//   physics.addMesh(ball)
// }

let floor
// 地面
floor = new THREE.Mesh(
  new THREE.BoxGeometry(10, 1, 10),
  new THREE.ShadowMaterial({ color: 0x111111 }) //影子的颜色

)
floor.position.set(0, -1, 0)
scene.add(floor)

async function enablePhysics() {
  physics = await OimoPhysics()
  physics.addMesh(floor) //添加一个地面 --（第二个参数不写，表示为刚体）  
  // 创建完成后，刷新浏览器，我们发现页面没有任何变化，这是因为我们在addMesh方法中，没有设置第二个参数，默认为0，即代表小球不参与物理世界的运动，我们把其设置为1，
  physics.addMesh(ball, 1)
}

floor.receiveShadow = true
ball.castShadow = true

enablePhysics()

// OimoPhysics插件的使用

</script>